<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>发布订阅者</title>
    <style>
        #root,
        #app {
            border: 1px solid #eee;
            min-width: 500px;
            width: 600px;
            min-height: 200px;
            box-shadow: 5px 5px 10px rgba(0, 0, 0, 0.3);
        }
    </style>
</head>

<body>
    <h2>订阅视图-1</h2>
    <div id="app"></div>
    <h2>订阅视图-2</h2>
    <div id="root"></div>
    <script type="text/javascript">
        /**
         * 订阅器模型
         */
        const Dependency = {
            /**
             * 订阅容器
             */
            clientList: {},//深拷贝，浅拷贝
            /**
             * 增加订阅
             */
            subscribe: function (key, callback) {
                (this.clientList[key]) || (this.clientList[key] = []).push(callback)
            },
            /**
             * 发布消息
             */
            publish: function () {
                let keys = Array.prototype.shift.call(arguments),
                    callbacks = this.clientList[keys];
                if (!callbacks || callbacks.length === 0) {
                    return false
                }
                for (let i = 0, callback; callback = callbacks[i++];) {
                    callback.apply(this, arguments)
                }
            }
        }

        // 劫持方法
        const mvvm = function ({ data, tag, key, selector }) {
            // debugger
            let value = "", el = document.querySelector(selector);
            // 数据劫持
            Object.defineProperty(data, key, {
                set: function (newVal) {
                    value = newVal
                    Dependency.publish(tag, newVal)
                },
                get: function () {
                    return value
                }
            });
            //绑定观察者
            Dependency.subscribe(tag, function (text) {
                el.innerHTML = text
            })
        }
        let obj = {}
        mvvm({
            data: obj,
            tag: "view-1",
            key: "one",
            selector: "#root"
        })
        mvvm({
            data: obj,
            tag: "view-2",
            key: "two",
            selector: "#app"
        })

        obj.one = "《山居笔记》"
        obj.two = "《文化苦旅》"
    </script>
</body>

</html>